package com.data.biz.service.impl;

import com.data.biz.constant.FunctionTypeEnum;
import com.data.biz.constant.DipTableResult;
import com.data.biz.constant.TimeFormatConstant;
import com.data.biz.domain.*;
import com.data.biz.mapper.*;
import com.data.biz.service.IBizDipService;
import com.data.biz.utils.ExcelFormatUtil;
import com.data.biz.vo.SensorVo.dip.GraphGroupVo;
import com.data.biz.vo.SensorVo.dip.GraphOneMapVo;
import com.data.biz.vo.SensorVo.dip.DipTableVo;
import org.apache.commons.collections.CollectionUtils;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;


@Service
public class BizDipservice implements IBizDipService {
    @Autowired
    private DipDataMapperEx dipDataMapperEx;

    @Autowired
    private WindPointMapper windPointMapper;

    @Autowired
    private TableCountMapper countMapper;

    @Autowired
    private DipDayMapper dipDayMapper;

    @Override
    public DipTableResult getDipTableDataByPoint(Integer pointId, String startDate, String endDate, Integer page, Integer pageSize) {
        DipTableResult result = new DipTableResult();

        List<DipTableVo> resultList = new ArrayList<>();
        WindPoint pointSearchEntity = new WindPoint();
        pointSearchEntity.setId(pointId);
        WindPoint point = windPointMapper.selectByPrimaryKey(pointId);
        String tableName = getTableByPoint(point);
        int totalCount = 0;
        List<DipData> list;
        if (page == null && pageSize == null) {
            ;
            list = dipDataMapperEx.selectDipTable(tableName, startDate, endDate, null, null);
        } else {
            totalCount = dipDataMapperEx.selectCount(tableName, startDate, endDate);
            list = dipDataMapperEx.selectDipTable(tableName, startDate, endDate, (page - 1) * pageSize, pageSize);
        }


        for (DipData data : list) {
            DipTableVo vo = new DipTableVo();
            BeanUtils.copyProperties(data, vo);
            vo.setCreateTime(TimeFormatConstant.formatSec.format(data.getCreateTime()));
            vo.setXMean(data.getxMean().toString());
            vo.setXMax(data.getxMax().toString());
            vo.setXMin(data.getxMin().toString());
            vo.setXEff(data.getxEff().toString());

            vo.setYMean(data.getyMean().toString());
            vo.setYMax(data.getyMax().toString());
            vo.setYMin(data.getyMin().toString());
            vo.setYEff(data.getyEff().toString());

            vo.setZMean(data.getzMean().toString());
            vo.setZMax(data.getxMax().toString());
            vo.setZMin(data.getxMin().toString());
            vo.setZEff(data.getxEff().toString());

            resultList.add(vo);
        }
        result.setList(resultList);
        result.setTotalCount(totalCount);
        return result;
    }


    @Override
    public ResponseEntity<byte[]> exportDipExcel(HttpServletRequest request, HttpServletResponse response, Integer pointId, String startDate, String endDate) {
        try {
            List<DipTableVo> list = getDipTableDataByPoint(pointId, startDate, endDate, null, null).getList();
            downloadService baseFrontController = new downloadService();
            WindPoint point = windPointMapper.selectByPrimaryKey(pointId);
            return baseFrontController.buildResponseEntity(export((List<DipTableVo>) list), "测点" + point.getPointName() + "倾角数据.xls");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    private String getTableByPoint(WindPoint point) {
        String tableName = point.getIp() + "_" + FunctionTypeEnum.getIndexById(point.getFunctionId()).toLowerCase(Locale.ROOT) + "_" + point.getCom();

        String name = tableName.replace('.', '_');
        return name;
    }


    public GraphGroupVo getDipDataGroupGraph(Integer pointId, String startDate, String endDate) {
        GraphGroupVo result = new GraphGroupVo();
        List<List<GraphOneMapVo>> resultList = new ArrayList<>();
        List<GraphOneMapVo> oneMapVoListX = new ArrayList<>();
        List<GraphOneMapVo> oneMapVoListY = new ArrayList<>();
        List<GraphOneMapVo> oneMapVoListZ = new ArrayList<>();

        //对应倾角的XYZ

        WindPoint point = windPointMapper.selectByPrimaryKey(pointId);
        String tableName = getTableByPoint(point);

        List<DipData> list = dipDataMapperEx.selectDipTable(tableName, startDate, endDate, null, null);
        LinkedHashMap<String, List<DipData>> map = new LinkedHashMap<>();
        for (DipData data : list) {
            String group = TimeFormatConstant.formatSec.format(data.getCreateTime());
            if (map.containsKey(group)) {
                List<DipData> mapList = map.get(group);
                mapList.add(data);
            } else {
                List<DipData> mapList = new ArrayList<>();
                mapList.add(data);
                map.put(group, mapList);
            }
        }


        for (String key : map.keySet()) {
            GraphOneMapVo voX = new GraphOneMapVo();
            GraphOneMapVo voY = new GraphOneMapVo();
            GraphOneMapVo voZ = new GraphOneMapVo();


            List<DipData> sourceList = map.get(key);

            List<String> dataListX = new ArrayList<>();
            List<String> dataListY = new ArrayList<>();
            List<String> dataListZ = new ArrayList<>();

            for (DipData data : sourceList) {
                dataListX.add(data.getxMean().setScale(3, RoundingMode.HALF_UP).toString());
                dataListX.add(data.getxMax().setScale(3, RoundingMode.HALF_UP).toString());
                dataListX.add(data.getxMin().setScale(3, RoundingMode.HALF_UP).toString());
                dataListX.add(data.getxEff().setScale(3, RoundingMode.HALF_UP).toString());
                dataListY.add(data.getyMean().setScale(3, RoundingMode.HALF_UP).toString());
                dataListY.add(data.getyMax().setScale(3, RoundingMode.HALF_UP).toString());
                dataListY.add(data.getyMin().setScale(3, RoundingMode.HALF_UP).toString());
                dataListY.add(data.getyEff().setScale(3, RoundingMode.HALF_UP).toString());
                dataListZ.add(data.getzMean().setScale(3, RoundingMode.HALF_UP).toString());
                dataListZ.add(data.getzMax().setScale(3, RoundingMode.HALF_UP).toString());
                dataListZ.add(data.getzMin().setScale(3, RoundingMode.HALF_UP).toString());
                dataListZ.add(data.getzEff().setScale(3, RoundingMode.HALF_UP).toString());
            }
            voX.setDataList(dataListX);
            voX.setTime(key);
            voY.setDataList(dataListY);
            voY.setTime(key);
            voZ.setDataList(dataListZ);
            voZ.setTime(key);
            oneMapVoListX.add(voX);
            oneMapVoListY.add(voY);
            oneMapVoListZ.add(voZ);
        }
        resultList.add(oneMapVoListX);
        resultList.add(oneMapVoListY);
        resultList.add(oneMapVoListZ);
        result.setList(resultList);
        return result;
    }


    public GraphGroupVo getDipDataStatistic(Integer pointId, String startDate, String endDate) {
        GraphGroupVo result = new GraphGroupVo();
        List<List<GraphOneMapVo>> resultList = new ArrayList<>();
        List<GraphOneMapVo> oneMapVoListX = new ArrayList<>();
        List<GraphOneMapVo> oneMapVoListY = new ArrayList<>();
        List<GraphOneMapVo> oneMapVoListZ = new ArrayList<>();

        //对应倾角的XYZ

        WindPoint point = windPointMapper.selectByPrimaryKey(pointId);

        DipDayExample example = new DipDayExample();
        DipDayExample.Criteria criteria = example.createCriteria();
        criteria.andPointIdEqualTo(pointId);
        criteria.andDayGreaterThan(Integer.parseInt(startDate.replace("-","")));
        criteria.andDayLessThan(Integer.parseInt(endDate.replace("-","")));

        List<DipDay> list = dipDayMapper.selectByExample(example);
        LinkedHashMap<Integer, List<DipDay>> map = new LinkedHashMap<>();
        for (DipDay data : list) {
            Integer group = data.getDay();
            if (map.containsKey(group)) {
                List<DipDay> mapList = map.get(group);
                mapList.add(data);
            } else {
                List<DipDay> mapList = new ArrayList<>();
                mapList.add(data);
                map.put(group, mapList);
            }
        }


        for (Integer key : map.keySet()) {
            GraphOneMapVo voX = new GraphOneMapVo();
            GraphOneMapVo voY = new GraphOneMapVo();
            GraphOneMapVo voZ = new GraphOneMapVo();


            List<DipDay> sourceList = map.get(key);

            List<String> dataListX = new ArrayList<>();
            List<String> dataListY = new ArrayList<>();
            List<String> dataListZ = new ArrayList<>();

            for (DipDay data : sourceList) {
                dataListX.add(data.getxMax().toString());
                dataListY.add(data.getyMax().toString());
                dataListZ.add(data.getzMax().toString());
            }
            voX.setDataList(dataListX);
            voX.setTime(key.toString());
            voY.setDataList(dataListY);
            voY.setTime(key.toString());
            voZ.setDataList(dataListZ);
            voZ.setTime(key.toString());
            oneMapVoListX.add(voX);
            oneMapVoListY.add(voY);
            oneMapVoListZ.add(voZ);
        }
        resultList.add(oneMapVoListX);
        resultList.add(oneMapVoListY);
        resultList.add(oneMapVoListZ);
        result.setList(resultList);
        return result;
    }



    public static void main(String[] args){
        BigDecimal aa = new BigDecimal(0.12);
        System.out.println(aa.setScale(3,4));
    }
    public void doSaveDip(List<String> address, List<String> data) {
        String ip = address.get(0);
        String type = address.get(1);
        String com = address.get(2);
        String tableName = ip.replaceAll("\\.", "_") + "_" + type + "_" + com;
        WindPointExample example = new WindPointExample();
        WindPointExample.Criteria criteria = example.createCriteria();
        criteria.andIpEqualTo(ip);
        criteria.andComEqualTo(com);
        criteria.andFunctionTypeEqualTo((type.toUpperCase(Locale.ROOT)));
        WindPoint point = windPointMapper.selectByExample(example).get(0);
        List<DipData> saveList = new ArrayList<>();
        for (String entity : data) {
            entity = entity.replaceAll("\\[", "").replaceAll("\\]", "");
            List<String> finalList = Arrays.asList(entity.split(","));
            BigDecimal test = new BigDecimal(999999);
            try {
                for (int i = 0; i < finalList.size(); i++) {
                    if (new BigDecimal(finalList.get(i)).compareTo(test) > 0) {
                        //最后一个是时间，会大于999999
                        if (i != finalList.size() - 1) {
                            throw new Exception();
                        }
                    }
                }
            } catch (Exception e) {
                continue;
            }

            setDipDataList(saveList, finalList, point);
        }
        if (CollectionUtils.isNotEmpty(saveList)) {
//            dipDataMapperEx.batchInsert(saveList, tableName);
        }
        //
        setLastData(point, saveList);
        setDayData(point, saveList);
    }

    public void doSaveSingleDipData(DipData data, String deviceId) {
        WindPointExample example = new WindPointExample();
        WindPointExample.Criteria criteria = example.createCriteria();
        criteria.andFunctionTypeEqualTo("DIP");
        criteria.andIdEqualTo(1);
        WindPoint point = windPointMapper.selectByExample(example).get(0);
        List<DipData> saveList = new ArrayList<>();
        data.setPointId(point.getId());
        saveList.add(data);
        String tableName ="123_456_677_111_dip_com7";
        if (CollectionUtils.isNotEmpty(saveList)) {
            dipDataMapperEx.batchInsert(saveList, tableName);
        }
        //
        setLastData(point, saveList);
        setDayData(point, saveList);
    }


    public void setLastData(WindPoint point, List<DipData> saveList) {
        TableCountExample example1 = new TableCountExample();
        TableCountExample.Criteria criteria1 = example1.createCriteria();
        criteria1.andPointIdEqualTo(point.getId());
        List<TableCount> countlist = countMapper.selectByExample(example1);
        TableCount count = countlist.get(0);
        DipData data = saveList.get(saveList.size() - 1);
        count.setFanId(point.getFanId());
        count.setFunctionId(point.getFunctionId());
        count.setFunctionType(FunctionTypeEnum.getIndexById(point.getFunctionId()));
        count.setLastId(data.getId());
        count.setValue1(data.getxMean().toString());
        count.setValue2(data.getxMin().toString());
        count.setValue3(data.getxMax().toString());
        count.setValue4(data.getxEff().toString());
        ///
        count.setValue5(data.getyMean().toString());
        count.setValue6(data.getyMin().toString());
        count.setValue7(data.getyMax().toString());
        count.setValue8(data.getyEff().toString());
        //
        count.setValue9(data.getzMean().toString());
        count.setValue10(data.getzMin().toString());
        count.setValue11(data.getzMax().toString());
        count.setValue12(data.getzEff().toString());
        count.setCreateTime(data.getCreateTime());
        countMapper.updateByPrimaryKeySelective(count);
    }

    public void setDayData(WindPoint point, List<DipData> saveList) {
        Integer day = Integer.parseInt(TimeFormatConstant.formatToDay.format(saveList.get(0).getCreateTime()));
        DipDayExample example1 = new DipDayExample();
        DipDayExample.Criteria criteria1 = example1.createCriteria();
        criteria1.andPointIdEqualTo(point.getId());
        criteria1.andDayEqualTo(day);
        List<DipDay> list = dipDayMapper.selectByExample(example1);
        DipDay dayData;
        if (CollectionUtils.isNotEmpty(list)) {
            dayData = list.get(0);
        } else {
            dayData = new DipDay();
        }
        for (DipData data : saveList) {
            BigDecimal xMax = data.getxMax();
            BigDecimal yMax = data.getyMax();
            BigDecimal zMax = data.getzMax();
            if (dayData.getxMax() == null) {
                dayData.setxMax(xMax);
            } else if (xMax.compareTo(dayData.getxMax()) > 0) {
                dayData.setxMax(xMax);
            }
            if (dayData.getyMax() == null) {
                dayData.setyMax(yMax);
            } else if (yMax.compareTo(dayData.getyMax()) > 0) {
                dayData.setyMax(yMax);
            }
            if (dayData.getzMax() == null) {
                dayData.setzMax(zMax);
            } else if (zMax.compareTo(dayData.getzMax()) > 0) {
                dayData.setzMax(zMax);
            }
        }
        if (CollectionUtils.isNotEmpty(list)) {
            dayData.setDay(day);
            dipDayMapper.updateByPrimaryKeySelective(dayData);
        } else {
            dayData.setPointId(point.getId());
            dayData.setFanId(point.getFanId());
            dayData.setDay(day);
            dayData.setIsDelete((short) 0);
            dipDayMapper.insert(dayData);
        }

    }


    private static void setDipDataList(List<DipData> saveList, List<String> finalList, WindPoint point) {
        DipData accData = new DipData();
        accData.setPointId(point.getId());
        accData.setId(Long.valueOf(finalList.get(0).trim()));
        accData.setxMean(new BigDecimal(finalList.get(2).trim()));
        accData.setxMin(new BigDecimal(finalList.get(3).trim()));
        accData.setxMax(new BigDecimal(finalList.get(4).trim()));
        accData.setxEff(new BigDecimal(finalList.get(5).trim()));
        accData.setyMean(new BigDecimal(finalList.get(6).trim()));
        accData.setyMax(new BigDecimal(finalList.get(7).trim()));
        accData.setyMin(new BigDecimal(finalList.get(8).trim()));
        accData.setyEff(new BigDecimal(finalList.get(9).trim()));
        accData.setzMean(new BigDecimal(finalList.get(10).trim()));
        accData.setzMax(new BigDecimal(finalList.get(11).trim()));
        accData.setzMin(new BigDecimal(finalList.get(12).trim()));
        accData.setzEff(new BigDecimal(finalList.get(13).trim()));
        accData.settMean(new BigDecimal(finalList.get(14).trim()));
        accData.setIsDelete((short) 0);
        Long time = Long.parseLong(finalList.get(27).replace(".0", "")) * 1000l;
        Date date = new Date(time);
        accData.setCreateTime(date);
        saveList.add(accData);
    }


    public WindPoint getPointByEntity(WindPoint entity) {
        WindPointExample example = new WindPointExample();
        WindPointExample.Criteria criteria = example.createCriteria();
        if (entity.getFanId() != null) {
            criteria.andFanIdEqualTo(entity.getFanId());
        }
        if (entity.getFunctionId() != null) {
            criteria.andFunctionIdEqualTo(entity.getFunctionId());
        }
        if (entity.getId() != null) {
            criteria.andIdEqualTo(entity.getId());
        }
        criteria.andIsDeleteEqualTo((short) 0);
        List<WindPoint> list = windPointMapper.selectByExample(example);
        if (list != null && list.size() != 0) {
            return list.get(0);
        } else {
            return null;
        }
    }


    private InputStream export(List<DipTableVo> list) {
        ByteArrayOutputStream output = null;
        InputStream inputStream1 = null;
        SXSSFWorkbook wb = new SXSSFWorkbook(1000);// 保留1000条数据在内存中

        Sheet sheet = wb.createSheet();
        // 设置报表头样式
        CellStyle header = ExcelFormatUtil.headSytle(wb);// cell样式
        CellStyle content = ExcelFormatUtil.contentStyle(wb);// 报表体样式

        // 每一列字段名
        String[] strs = new String[]{
                "x加速度平均值", "x加速度最小值", "x加速度最大值", "x加速度有效值",
                "y加速度平均值", "y加速度最小值", "y加速度最大值", "y加速度有效值",
                "z加速度平均值", "z加速度最小值", "z加速度最大值", "z加速度有效值",
                "采集时间"};

        // 字段名所在表格的宽度
        int[] ints = new int[]{5000, 5000, 5000, 5000, 5000, 5000, 5000, 5000, 5000, 5000, 5000, 5000, 5000};

        // 设置表头样式
        ExcelFormatUtil.initTitleEX(sheet, header, strs, ints);

        if (list != null && list.size() > 0) {
            for (int i = 0; i < list.size(); i++) {
                DipTableVo vo = list.get(i);
                Row row = sheet.createRow(i + 1);
                int j = 0;
                Cell cell = row.createCell(j++);
                cell.setCellValue(vo.getXMean()); //
                cell.setCellStyle(content);

                cell = row.createCell(j++);
                cell.setCellValue(vo.getXMax()); //
                cell.setCellStyle(content);

                cell = row.createCell(j++);
                cell.setCellValue(vo.getXMin()); //
                cell.setCellStyle(content);

                cell = row.createCell(j++);
                cell.setCellValue(vo.getXEff()); //
                cell.setCellStyle(content);

                ///////Y
                cell = row.createCell(j++);
                cell.setCellValue(vo.getYMean()); //
                cell.setCellStyle(content);

                cell = row.createCell(j++);
                cell.setCellValue(vo.getYMax()); //
                cell.setCellStyle(content);

                cell = row.createCell(j++);
                cell.setCellValue(vo.getYMin()); //
                cell.setCellStyle(content);

                cell = row.createCell(j++);
                cell.setCellValue(vo.getYEff()); //
                cell.setCellStyle(content);

                ////////////
                cell = row.createCell(j++);
                cell.setCellValue(vo.getZMean()); //
                cell.setCellStyle(content);

                cell = row.createCell(j++);
                cell.setCellValue(vo.getZMax()); //
                cell.setCellStyle(content);

                cell = row.createCell(j++);
                cell.setCellValue(vo.getZMin()); //
                cell.setCellStyle(content);

                cell = row.createCell(j++);
                cell.setCellValue(vo.getZEff()); //
                cell.setCellStyle(content);


                cell = row.createCell(j++);
                cell.setCellValue(vo.getCreateTime()); // 采集时间
                cell.setCellStyle(content);
            }
        }
        try {
            output = new ByteArrayOutputStream();
            wb.write(output);
            inputStream1 = new ByteArrayInputStream(output.toByteArray());
            output.flush();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (output != null) {
                    output.close();
                    if (inputStream1 != null)
                        inputStream1.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return inputStream1;
    }


}
